#pragma once

#include "njm_img.hpp"
#include "njm_device.hpp"
#include "njm_buffer.hpp"

#include <vulkan/vulkan.h>
#include <unordered_map>
#include <memory>
#include <string>

namespace njm
{
    struct TextureImgBinding
    {
        std::string texName;
        std::string imgName;
    };

    class NjmTexture
    {
    public:
    using id_t = std::string;
    using Map = std::unordered_map<id_t, NjmTexture>;

        NjmTexture(NjmDevice& device, const std::string& name, const std::shared_ptr<NjmImg>& img);
        ~NjmTexture();
        NjmTexture(const NjmTexture&) = delete;
        NjmTexture& operator=(const NjmTexture&) = delete;
        NjmTexture(NjmTexture&&) = default;
        NjmTexture& operator=(NjmTexture&&) = default;

        const id_t& getId() const { return id; }
        const std::string& getName() const { return name; }
        std::shared_ptr<NjmImg> getImg() const { return img; }
        
        VkImage getImage() const { return image; }
        VkImageView getImageView() const { return imageView; }
        VkSampler getSampler() const { return sampler; }
        VkDescriptorImageInfo getCombinedDescriptor() const;
        VkDescriptorImageInfo getImageDescriptor() const;
        VkDescriptorImageInfo getSamplerDescriptor() const;

        const VkImageType getImageType() const { return VK_IMAGE_TYPE_2D; }
        const VkImageViewType getImageViewType() const { return VK_IMAGE_VIEW_TYPE_2D; }
        const VkImageUsageFlags getImageUsage() const { return VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; }
        const VkImageLayout getImageLayout() const { return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; }
        const VkImageAspectFlags getImageAspect() const { return VK_IMAGE_ASPECT_COLOR_BIT; }
        const VkExtent2D getVkExtent() const { return img->getVkExtent(); }
        const VkImageTiling getImageTiling() const { return VK_IMAGE_TILING_OPTIMAL; }

    private:
        NjmDevice& device;
        VkImage image = VK_NULL_HANDLE;
        VkDeviceMemory memory = VK_NULL_HANDLE;
        VkImageView imageView = VK_NULL_HANDLE;
        VkSampler sampler = VK_NULL_HANDLE;
        
        id_t id;
        std::string name;
        std::shared_ptr<NjmImg> img;
        
        void createTextureImage();
        void createTextureImageView();
        void createTextureSampler();
    };
}
